package net.atomarrow.action;

import net.atomarrow.aop.ControllerInterceptor;
import net.atomarrow.controllers.Controller;
import net.atomarrow.ioc.ActionContext;
import net.atomarrow.ioc.ApplicationContext;
import net.atomarrow.render.Render;

import java.util.Iterator;

/**
 * Action执行
 * @author Michael
 *
 */
public class ActionInvocation {
    private Action action;
    private Controller controller;
    private Iterator<ControllerInterceptor> interceptorsIter;

    public ActionInvocation(Action action) {
        this.action=action;
        this.controller=ApplicationContext.get(action.getControllerClass());
        interceptorsIter=action.getInterceptors().iterator();
    }

    public void doInvoke(){
    	   Render render = invoke();
    	   //处理render可能出现的错误
    	   try{
    		   render.render();
    	   }catch (Exception e) {
	   			ActionContext context = ActionContext.getContext();
	   			context.setControllerOrInterceptorException(e);
	   			throw e;
    	   }
    }
    public Render invoke(){
    	try{
            while(interceptorsIter.hasNext()){
                return interceptorsIter.next().intercept(this);
            }
            Render render = (Render) action.getMethod().invoke(controller, getParamValues());
            //如果service有错误,需要处理返回前台
            if(ActionContext.getContext().getServiceException()!=null){
            	Throwable  e=ActionContext.getContext().getServiceException();
        		return controller.renderError(parseError(e));
            }
            ActionContext.getContext().setRender(render);
            return render;
    	}catch (Exception e) {
    		//如果controller有错误需要处理返回前台
			e.printStackTrace();
			ActionContext.getContext().setControllerOrInterceptorException(e);
    		return controller.renderError(parseError(e));
		}
    }

    /**
     * 请求参数的值
     * @return
     */
    private Object[] getParamValues() {
        if (action.getParamInfos() == null) {
            return null;
        }


        Object[] values = new Object[action.getParamInfos().length];

        for (int i = 0; i < action.getParamInfos().length; i++) {
            values[i] = action.getParamInfos()[i].extractValueFromRequest((AtomarrowRequest) ActionContext.getContext().getRequest());
        }

        return values;
    }

    /**
     * 解析出错误信息
     * @param e
     * @return
     */
    private String parseError(Throwable e){
    	StringBuilder sb = new StringBuilder();
		Throwable c=e.getCause();
		if(c==null){
			c=e;
		}
        sb.append(c);
		sb.append("<br>");
		for(StackTraceElement ste:c.getStackTrace()){
			sb.append(ste.toString());
			sb.append("<br>");
		}
		return sb.toString();
    }
    public Action getAction() {
        return action;
    }

    public void setAction(Action action) {
        this.action = action;
    }

    public Controller getController() {
        return controller;
    }

    public void setController(Controller controller) {
        this.controller = controller;
    }
    

}
